/******************************************************************
 * Copyright (c) 2007 - 2007, Simon Guerard, All rights reserved.
 * 
 * Projet de jeu de course au large.
 * 
 * This File is part of Sail-Race
 * 
 * Sail-Race is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * Sail-Race is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * Sail-Race; if not, write to the Free Software Foundation, Inc., 51 Franklin St,
 * Fifth Floor, Boston, MA 02110-1301 USA
 */

package net.simcafamily.sailrace.core;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JPanel;

import net.simcafamily.sailrace.listener.QuitListener;
import net.simcafamily.sailrace.spring.ContextFactory;

import org.apache.commons.lang3.StringUtils;

/**
 * @version $Revision$
 * @author $Author$
 */
public class BaseControleur implements IControleur, ActionListener {

    // les actions a controler
    private Map<String, InfosAction> actions = new HashMap<String, InfosAction>();

    // le nom de la 1ere action
    private String firstActionName;

    // le nom de la derniere action
    private String lastActionName;

    private Synchronisateur synchro;

    // frame principale de l'application.
    private BaseVueJFrame baseVue;

    /**
     * Constructeur par defaut.
     */
    public BaseControleur() {
    }

    /**
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    @Override
    public void actionPerformed(final ActionEvent pE) {
	run();
    }

    /**
     * @return Returns the actions.
     */
    public Map<String, InfosAction> getActions() {
	return actions;
    }

    /**
     * @return the baseVue
     */
    public final BaseVueJFrame getBaseVue() {
	return baseVue;
    }

    /**
     * @return Returns the firstActionName.
     */
    public String getFirstActionName() {
	return firstActionName;
    }

    /**
     * @return Returns the lastActionName.
     */
    public String getLastActionName() {
	return lastActionName;
    }

    /**
     * @return the synchro
     */
    public final Synchronisateur getSynchro() {
	return synchro;
    }

    // le moteur d'execution des actions
    @Override
    public void run() {
	baseVue.init();
	baseVue.run();

	// variables locales
	IForward forward = null;

	// boucle d'execution des actions
	forward = (InfosAction) ContextFactory.getContext().getBean(
		firstActionName);
	while (forward != null
		&& (forward.getActionName() != null
			&& !forward.getActionName().equals(lastActionName) || forward
			.getActionName() == null)) {
	    // test if there's anything to do in an action
	    if (!forward.isVueInstance()) {
		InfosAction configAction = (InfosAction) forward;
		// execute the action there is one
		if (configAction.getAction() != null) {
		    baseVue.setActionName(null);
		    // execute the action
		    String etat = configAction.getAction().execute();
		    // get the view attached with the return state
		    forward = configAction.getEtats().get(etat);
		    // if view == null, config error
		    if (forward == null) {
			throw new RuntimeException("L'etat [" + etat
				+ "] de l'action ["
				+ configAction.getActionName()
				+ "] n'a pas ete configure correctement");
		    }
		} else {
		    // pas d'action - directement la vue
		    forward = configAction.getVue();
		}
	    }
	    if (forward.isVueInstance()) {
		// on affiche la vue en se synchronisant avec elle
		synchro.reset();
		final Component panelVue = ((IView) forward).buildContentPane();

		final Component c = baseVue.getManagerFrame().getContent();
		if (c != null && c instanceof QuitListener) {
		    final QuitListener q = (QuitListener) c;
		    q.quit();
		    baseVue.removeQuitListener(q);
		}
		baseVue.getManagerFrame().setContent(new JPanel());
		baseVue.validate();
		baseVue.getManagerFrame().setContent(panelVue);
		baseVue.validate();
		baseVue.getManagerFrame().repaint();
		synchro.waitOne();
		// action suivante
		String actionName = baseVue.getActionName();
		if (StringUtils.isEmpty(actionName)) {
		    actionName = forward.getActionName();
		}
		if (StringUtils.isNotEmpty(actionName)) {
		    // on recupere la config de l'action
		    forward = (InfosAction) ContextFactory.getContext()
			    .getBean(actionName);
		    if (forward == null) {
			// erreur de config - on s'arrete
			throw new RuntimeException("L'action [" + actionName
				+ "] n'a pas ete configuree correctement");
		    }
		}
	    }
	}
    }

    /**
     * @param actions
     *            The actions to set.
     */
    public void setActions(final Map<String, InfosAction> actions) {
	this.actions = actions;
    }

    /**
     * @param pBaseVue
     *            the baseVue to set
     */
    public final void setBaseVue(final BaseVueJFrame pBaseVue) {
	baseVue = pBaseVue;
    }

    /**
     * @param firstActionName
     *            The firstActionName to set.
     */
    public void setFirstActionName(final String firstActionName) {
	this.firstActionName = firstActionName;
    }

    /**
     * @param lastActionName
     *            The lastActionName to set.
     */
    public void setLastActionName(final String lastActionName) {
	this.lastActionName = lastActionName;
    }

    /**
     * @param pSynchro
     *            the synchro to set
     */
    public final void setSynchro(final Synchronisateur pSynchro) {
	synchro = pSynchro;
    }

}
